import { ITableData } from "@/store";
import { ComputedRef } from "@vue/composition-api";

export const check = {
	isNull(val: any): val is undefined | null {
		return typeof val === "undefined" || val === null;
	},

	isNumOrStr(val: any): val is string | number {
		return typeof val === "string" || typeof val === "number";
	},

	isJSON(val: any) {
		return val.map && val.filter;
	},

	isObjectFullOfNull(val: { [p: string]: any }) {
		for (let item of Object.values(val)) {
			if (typeof item === "string" && item.length > 0) {
				return false;
			}
		}
		return true;
	},
};

export type FilledSearchMode = { key: string; val: string; weight: number }[];

export interface ISearchModeConfig {
	mode: string | null | FilledSearchMode | string[];
	able: boolean;
	label: string;
	$$val?: string;
	sort: boolean;
}

export interface Config {
	data: string;
	title: string;
	index: boolean;
	footer: boolean;
	removeFirstLine: boolean;
	config: ISearchModeConfig[];

	onLoadData: (data: ITableData) => void;
	onChangePage: (page: number) => void;
	onSortData: (
		key: string,
		order: 1 | -1
	) => void | ((a: string, b: string) => number);
	injectJson: (
		config: Config
	) => Omit<{ [key: string]: number | string }, "data" | "count" | "name">;
	meta: {
		[key: string]: any;
	};
}

export const defaultState: Config = {
	data: "",
	config: [],
	footer: true,
	index: false,
	title: document.title,
	removeFirstLine: true,
	onLoadData: () => {},
	onSortData: () => {},
	onChangePage: () => {},
	injectJson: () => ({}),
	meta: {},
};

export function mergeConfigItem(config: Config["config"][0]) {
	/**
	 * 判断是否设置了able(可见性)，默认为{true}
	 */
	if (check.isNull(config.able)) {
		config.able = true;
	}

	/**
	 * 判断是否设置了sort(是否可排序)，默认为{true}
	 */
	if (check.isNull(config.sort)) {
		config.sort = false;
	}

	/**
	 * 判断是否设置了mode，默认为{null}
	 */
	if (check.isNull(config.mode)) {
		config.mode = null;
	} else if (check.isNumOrStr(config.mode)) {
		if (config.mode !== "[=]") {
			config.mode = "[?]";
		}
	}

	/**
	 * mode属性规范化
	 */
	if (Array.isArray(config.mode) && check.isNumOrStr(config.mode[0])) {
		config.mode = (config.mode as any).map((item: any, weight: number) => ({
			key: String(item),
			val: String(item),
			weight,
		}));
	}

	if (Array.isArray(config.mode)) {
		config.mode = (
			config.mode as { key: string; val: string; weight: number }[]
		).map((item, weight) => ({
			key: item.key,
			val: item.val,
			weight: item.weight ? item.weight : weight,
		}));
	}

	return config;
}

export function mergeOptions(
	config?: Partial<Config> | Partial<Config>[]
): Config {
	const options = { ...defaultState, ...config };
	options.config.forEach((config) => (config = mergeConfigItem(config)));
	return options;
}

export function noneOr<T>(val: T | undefined, defaultVal: T) {
	if (typeof val === "undefined") {
		return defaultVal;
	}

	return val;
}

export function checkCountDownList(cdown: ComputedRef<any>) {
	const flag =
		cdown.value.date &&
		cdown.value.name &&
		typeof cdown.value.date == "string" &&
		typeof cdown.value.name == "string";

	return flag;
}
